﻿namespace zijian666.Data.SqlElements;

/// <summary>
/// SQL 搜索器
/// </summary>
public interface ISqlSearcher
{
    /// <summary>
    /// 获取实体类型。
    /// </summary>
    Type EntityType { get; }
}

/// <summary>
/// SQL 搜索器泛型约定
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ISqlSearcher<T> : ISqlSearcher
{
    /// <summary>
    /// 获取实体类型。
    /// </summary>
    Type ISqlSearcher.EntityType => typeof(T);
}

/// <summary>
/// SQL 搜索器扩展方法
/// </summary>
public static class SqlSearcherExtensions
{
    private static readonly ConcurrentDictionary<Type, SqlOperatorInfo[]> CACHE = new();

    /// <summary>
    /// 表示 SQL 操作符信息。
    /// </summary>
    /// <param name="Property">属性信息。</param>
    /// <param name="Attribute">SQL 操作符属性。</param>
    public record SqlOperatorInfo(PropertyInfo Property, ISqlOperatorAttribute Attribute);

    /// <summary>
    /// 构建 SQL 查询。
    /// </summary>
    /// <typeparam name="T">实体类型。</typeparam>
    /// <param name="searcher">SQL 搜索器。</param>
    /// <returns>构建的 SQL 查询。</returns>
    public static SqlQuery Build<T>(this ISqlSearcher<T>? searcher)
    {
        if (searcher is null)
        {
            var table = new SqlTable(default, typeof(T));
            return new SqlQuery
            {
                Table = table
            };
        }
        return Build((ISqlSearcher)searcher);
    }

    /// <summary>
    /// 构建 SQL 查询。
    /// </summary>
    /// <param name="searcher">SQL 搜索器。</param>
    /// <returns>构建的 SQL 查询。</returns>
    public static SqlQuery Build(this ISqlSearcher searcher)
    {
        var operators = CACHE.GetOrAdd(searcher.GetType(), CreateCache);
        var table = new SqlTable(default, searcher.EntityType);
        var conditions = new List<SqlCondition>();
        foreach (var op in operators)
        {
            var value = op.Property.GetValue(searcher);
            if (value is null)
            {
                continue;
            }

            var condition = op.Attribute.Build(table, op.Property, value);
            if (condition.IsEmpty)
            {
                continue;
            }
            conditions.Add(condition);
        }

        var where = new SqlWhere(SqlCondition.And(conditions));
        return new SqlQuery
        {
            Table = table,
            Select = default,
            Where = where
        };
    }

    /// <summary>
    /// 创建缓存。
    /// </summary>
    /// <param name="type">类型。</param>
    /// <returns>SQL 操作符信息数组。</returns>
    private static SqlOperatorInfo[] CreateCache(Type type)
    {
        return enumerable().ToArray();
        IEnumerable<SqlOperatorInfo> enumerable()
        {
            foreach (var property in type.GetProperties())
            {
                if (!property.CanRead)
                {
                    continue;
                }
                foreach (var attribute in property.GetCustomAttributes(true).OfType<ISqlOperatorAttribute>())
                {
                    yield return new SqlOperatorInfo(property, attribute);
                }
            }

        }
    }

    /// <summary>
    /// 为 SQL 查询添加排序。
    /// </summary>
    /// <param name="query">SQL 查询。</param>
    /// <param name="orderby">排序字符串。</param>
    /// <returns>添加排序后的 SQL 查询。</returns>
    public static SqlQuery OrderBy(this SqlQuery query, string orderby)
    {
        var items = new List<OrderItem>();
        if (query.OrderBy.Items is not null)
        {
            items.AddRange(query.OrderBy.Items);
        }
        foreach (var item in orderby.Split(','))
        {
            var parts = item.Split(' ');
            if (parts.Length == 0)
            {
                continue;
            }
            var column = new SqlColumn(query.Table, parts[0].Trim());
            var desc = parts.Length > 1 && string.Equals(parts[1].Trim(), "desc", StringComparison.OrdinalIgnoreCase);
            items.Add(new OrderItem(column, desc));
        }

        return query with
        {
            OrderBy = new SqlOrderBy(items)
        };
    }
}